package com.ziya.android.a3dmodel.course.two

import android.R
import android.opengl.GLES20
import android.opengl.GLSurfaceView.Renderer
import android.opengl.Matrix
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import java.nio.ShortBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10


class CourseTwoJVMRenderer : Renderer {
    private val vertextShaderCode =
        "attribute vec4 vPosition;" +
        "uniform mat4 vMatrix;" +
        "attribute vec4 aColor;" +
        "varying vec4 vColor;" +
        "void main() {" +
        "   gl_Position = vMatrix * vPosition;" +
        "   vColor = aColor;" +
        "}"
    private val fragmentShaderCode =
        "precision mediump float;" +
        "varying vec4 vColor;" +
        "void main() {" +
        "   gl_FragColor = vColor;" +
        "}"
    private val cubeCoors = floatArrayOf(
        -1.0f, 1.0f, 1.0f,  //正面左上0
        -1.0f, -1.0f, 1.0f,  //正面左下1
        1.0f, -1.0f, 1.0f,  //正面右下2
        1.0f, 1.0f, 1.0f,  //正面右上3
        -1.0f, 1.0f, -1.0f,  //反面左上4
        -1.0f, -1.0f, -1.0f,  //反面左下5
        1.0f, -1.0f, -1.0f,  //反面右下6
        1.0f, 1.0f, -1.0f //反面右上7
    )

    private val color = floatArrayOf(
        0f, 1f, 0f, 1f,
        0f, 1f, 0f, 1f,
        0f, 1f, 0f, 1f,
        0f, 1f, 0f, 1f,
        1f, 0f, 0f, 1f,
        1f, 0f, 0f, 1f,
        1f, 0f, 0f, 1f,
        1f, 0f, 0f, 1f
    )
    val index = shortArrayOf(
        6, 7, 4, 6, 4, 5,  //后面
        6, 3, 7, 6, 2, 3,  //右面
        6, 5, 1, 6, 1, 2,  //下面
        0, 3, 2, 0, 2, 1,  //正面
        0, 1, 5, 0, 5, 4,  //左面
        0, 7, 3, 0, 4, 7
    )
    private var program = 0
    private var vertexBuffer: FloatBuffer? = null
    //投影矩阵
    private val mProjectMatrix = FloatArray(16)

    //相机位置矩阵
    private val mViewMatrix = FloatArray(16)

    //计算变换矩阵
    private val mMVPMatrix = FloatArray(16)
    private var colorFloatBuffer: FloatBuffer? = null
    private var indexShortBuffer: ShortBuffer? = null
    override fun onSurfaceCreated(gl: GL10, p1: EGLConfig) {
        //将背景设置为灰色
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
        //开启深度测试
        GLES20.glEnable(GLES20.GL_DEPTH_TEST)
        GLES20.glDepthMask(true);
        //申请底层空间
        val byteBuffer = ByteBuffer.allocateDirect(cubeCoors.size * 4)
        byteBuffer.order(ByteOrder.nativeOrder())
        //将坐标数据转换为FloatBuffer，用以传入给OpenGL ES程序
        vertexBuffer = byteBuffer.asFloatBuffer()
        //将三角形坐标传入FloatBuffer
        vertexBuffer!!.put(cubeCoors)
        vertexBuffer!!.position(0)
        //申请底层空间
        val colorBuffer = ByteBuffer.allocateDirect(color.size * 4)
        colorBuffer.order(ByteOrder.nativeOrder())
        colorFloatBuffer = colorBuffer.asFloatBuffer()
        colorFloatBuffer!!.put(color)
        colorFloatBuffer!!.position(0)
        val indexBuffer = ByteBuffer.allocateDirect(index.size * 2)
        indexBuffer.order(ByteOrder.nativeOrder())
        indexShortBuffer = indexBuffer.asShortBuffer()
        indexShortBuffer!!.put(index)
        indexShortBuffer!!.position(0)
        //创建顶点着色器程序
        val vertexShader: Int = loadShader(GLES20.GL_VERTEX_SHADER, vertextShaderCode)
        //创建片元着色器程序
        val fragmentShader: Int = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)

        if (vertexShader == 0 || fragmentShader == 0) {
            return
        }
        //创建一个空的OpenGL ES程序
        program = GLES20.glCreateProgram()
        //将顶点着色器加入程序
        GLES20.glAttachShader(program, vertexShader)
        //将片元着色器加入程序
        GLES20.glAttachShader(program, fragmentShader)
        //连接到着色器程序中
        GLES20.glLinkProgram(program)
        //使用程序
        GLES20.glUseProgram(program)
    }

    override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
        println("屏幕比例:${width.toFloat() / height.toFloat()},width:${width},height:${height}")
        GLES20.glViewport(0, 0, width, height)
        val ratio = width.toFloat() / height.toFloat()
        //设置透视矩阵
        Matrix.frustumM(mProjectMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 20f)
        //设置相机位置
        Matrix.setLookAtM(mViewMatrix, 0, 5.0f, 5.0f, 10.0f,
            0f, 0f, 0f, 0f, 1.0f, 0.0f)
        //计算变换矩阵
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectMatrix, 0, mViewMatrix, 0)
    }

    override fun onDrawFrame(gl: GL10) {
        //使用当前清除颜色来填充窗口颜色
        // gl.glClear(GLES20.GL_COLOR_BUFFER_BIT)
        if (program == 0) return
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)
        //获取变换矩阵vMatrix成员句柄

        //获取变换矩阵vMatrix成员句柄
        val vMatrix = GLES20.glGetUniformLocation(program, "vMatrix")
        //设置vMatrix的值
        //设置vMatrix的值
        GLES20.glUniformMatrix4fv(vMatrix, 1, false, mMVPMatrix, 0)


        //获取顶点着色器的vPosition成员句柄
        val vPosition = GLES20.glGetAttribLocation(program, "vPosition")
        //启用vPosition句柄
        GLES20.glEnableVertexAttribArray(vPosition)
        //传的坐标数据
        GLES20.glVertexAttribPointer(vPosition, 3, GLES20.GL_FLOAT, false, 3 * 4, vertexBuffer)


        //获取顶点着色器的vColor成员句柄
        //获取顶点着色器的vColor成员句柄
        val aColor = GLES20.glGetAttribLocation(program, "aColor")
        //启用aColor句柄
        //启用aColor句柄
        GLES20.glEnableVertexAttribArray(aColor)
        //设置绘制三角形的颜色
        //设置绘制三角形的颜色
        GLES20.glVertexAttribPointer(aColor, 4, GLES20.GL_FLOAT, false, 4 * 4, colorFloatBuffer)
        //绘制三角形
        //绘制三角形
        GLES20.glDrawElements(
            GLES20.GL_TRIANGLES,
            index.size,
            GLES20.GL_UNSIGNED_SHORT,
            indexShortBuffer
        )
        //禁止顶点数组的句柄
        GLES20.glDisableVertexAttribArray(vPosition)
    }

    fun loadShader(type: Int, shaderCode: String?): Int {
        //创建空的着色器
        val shader = GLES20.glCreateShader(type)
        //将着色器程序加到着色器中
        GLES20.glShaderSource(shader, shaderCode)
        //编译色器程序
        GLES20.glCompileShader(shader)
        return shader
    }
}